package com.world.business.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.world.business.user.domain.User;
import com.world.business.user.domain.query.UserAddRequest;
import com.world.business.user.domain.query.UserChangePasswordRequest;
import com.world.business.user.domain.query.UserUpdateRequest;
import com.world.business.user.mapper.UserMapper;
import com.world.business.user.service.BaZi;
import com.world.business.user.service.IUserService;
import com.world.common.constants.RedisKeyConstants;
import com.world.common.enumeration.DelFlagEnum;
import com.world.common.exception.BusinessException;
import com.world.common.security.SecurityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 邓驴
 * @since 2023-05-13
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Value("${user.init.password}")
    private String initPassword;

    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    @Override
    public Long add(UserAddRequest request) {
        User user = BeanUtil.copyProperties(request, User.class);
        String loginName = getLoginName();
        user.setLoginName(loginName);
        String salt = getSalt();
        user.setSalt(salt);
        user.setPassword(getPassword(salt));
        user.setWrathOfHeavenId(0L);
        user.setCreateTime(LocalDateTime.now());
        user.setDelFlag(DelFlagEnum.NORMAL.getCode());
        user.setBirthBaZi(BaZi.getBaZi(request.getBirthday()));
        userMapper.insert(user);
        return user.getId();
    }

    @Override
    public void update(UserUpdateRequest request) {
        User user = this.userMapper.selectById(request.getId());
        if (BeanUtil.isEmpty(user)) {
            throw new BusinessException("用户不存在！");
        }
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class);
        updateWrapper.eq(User::getId, request.getId());
        updateWrapper.set(StrUtil.isNotBlank(request.getName()), User::getName, request.getName());
        updateWrapper.set(StrUtil.isNotBlank(request.getNickname()), User::getNickname, request.getNickname());
        updateWrapper.set(StrUtil.isNotBlank(request.getPicUrl()), User::getPicUrl, request.getPicUrl());
        updateWrapper.set(request.getAreaId() != null, User::getAreaId, request.getAreaId());
        updateWrapper.set(StrUtil.isNotBlank(request.getAddress()), User::getAddress, request.getAddress());
        updateWrapper.set(request.getReligiousSectId() != null, User::getReligiousSectId, request.getReligiousSectId());
        updateWrapper.set(request.getBeliefId() != null, User::getBeliefId, request.getBeliefId());
        updateWrapper.set(request.getRaceId() != null, User::getRaceId, request.getRaceId());
        updateWrapper.set(request.getBirthday() != null, User::getBirthday, request.getBirthday());
        updateWrapper.set(request.getBirthday() != null, User::getBirthBaZi, BaZi.getBaZi(request.getBirthday()));
        updateWrapper.set(request.getRealmId() != null, User::getRealmId, request.getRealmId());
        updateWrapper.set(request.getConstitutionId() != null, User::getConstitutionId, request.getConstitutionId());
        updateWrapper.set(request.getDeathday() != null, User::getDeathday, request.getDeathday());
        updateWrapper.set(request.getDeathday() != null, User::getDieBaZi, BaZi.getBaZi(request.getDeathday()));
        updateWrapper.set(StrUtil.isNotBlank(request.getDieReason()), User::getDieReason, request.getDieReason());
        updateWrapper.set(request.getStatus() != null, User::getStatus, request.getStatus());
        updateWrapper.set(StrUtil.isNotBlank(request.getRemark()), User::getRemark, request.getRemark());
        updateWrapper.set(StrUtil.isNotBlank(request.getType()), User::getType, request.getType());
        updateWrapper.set(User::getUpdateBy, SecurityUtils.getLoginUser().getName());
        updateWrapper.set(User::getUpdateById, SecurityUtils.getLoginUser().getId());
        updateWrapper.set(User::getUpdateTime, LocalDateTime.now());
        this.userMapper.update(null, updateWrapper);
    }

    @Override
    public void resetPassword(Long userId) {
        Long id = SecurityUtils.getLoginUser().getId();
        if (!id.equals(1L)) {
            throw new BusinessException(HttpStatus.HTTP_FORBIDDEN, "暂无权限");
        }

        if (userId.equals(1L)) {
            throw new BusinessException(HttpStatus.HTTP_FORBIDDEN, "该账号不允许修改！");
        }

        //重置密码
        User user = this.userMapper.selectById(userId);
        if (BeanUtil.isEmpty(user)) {
            throw new BusinessException(HttpStatus.HTTP_BAD_REQUEST, "该用户不存在!");
        }
        String salt = StrUtil.isBlank(user.getSalt()) ? getSalt() : user.getSalt();
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class);
        updateWrapper.set(StrUtil.isBlank(user.getSalt()), User::getSalt, salt);
        updateWrapper.set(User::getPassword, getPassword(salt));
        updateWrapper.eq(User::getId, userId);
        this.userMapper.update(null, updateWrapper);
    }

    @Override
    public void changePassword(UserChangePasswordRequest request) {
        User user = this.getById(SecurityUtils.getLoginUser().getId());
        String password = getPassword(request.getOldPw(), user.getSalt());
        if (!password.equals(user.getPassword())) {
            throw new SecurityException("旧密码不正确！");
        }
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class);
        updateWrapper.set(User::getPassword, getPassword(request.getNewPw(), user.getSalt()));
        updateWrapper.eq(User::getId, user.getId());
        this.userMapper.update(null, updateWrapper);

        //修改密码之后，设置token过期，需重新登录
        redisTemplate.delete(RedisKeyConstants.LOGIN_KEY + user.getId());
    }

    @Override
    public void initUser(Long userId) {
        Long id = SecurityUtils.getLoginUser().getId();
        if (!id.equals(1L)) {
            throw new BusinessException(HttpStatus.HTTP_FORBIDDEN, "暂无权限");
        }

        User user = this.getById(userId);
        if (BeanUtil.isEmpty(user)) {
            throw new BusinessException(HttpStatus.HTTP_BAD_REQUEST, "用户不存在！");
        }
        String salt = getSalt();

        //初始化用户信息
        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class);
        updateWrapper.set(User::getLoginName, getLoginName());
        updateWrapper.set(User::getSalt, salt);
        updateWrapper.set(User::getPassword, getPassword(salt));
        updateWrapper.eq(User::getId, userId);
        this.userMapper.update(null, updateWrapper);

    }

    /**
     * 获取密码加密盐
     *
     * @return String 盐
     */
    public String getSalt() {
        return RandomUtil.randomString(4);
    }

    /**
     * 获取密码
     *
     * @param salt 盐
     * @return Sting 密码
     * @author 邓驴
     * @date 2023/5/13 20:55
     **/
    public String getPassword(String salt) {
        return this.getPassword(initPassword, salt);
    }

    public String getPassword(String password, String salt) {
        MD5 md5 = MD5.create();
        return md5.digestHex(password + "-" + salt);
    }


    /**
     * 获取登录名称
     *
     * @return {@link String}
     */
    public String getLoginName() {
        return IdUtil.getSnowflakeNextIdStr();
    }
}
